﻿using System.Collections.Generic;
using UnityEngine;

namespace Simulation.Framework
{
    public class PanelManager : ManagerBehavior
    {
        private Dictionary<string, PanelBase> panelPool = new Dictionary<string, PanelBase>();
        [HideInInspector]
        public Canvas canvas;
        //public CanvasLook canvasLook;
        private List<PanelBase> activeNormalPanels = new List<PanelBase>();
        private List<PanelBase> activeMessageBoxPanels = new List<PanelBase>();
        private List<PanelBase> activeTopPanels = new List<PanelBase>();

        #region override

        public override void Init()
        {
            panelPool = new Dictionary<string, PanelBase>();
            canvas = GameObject.Find("PlayerCanvas").GetComponent<Canvas>();

            activeMessageBoxPanels = new List<PanelBase>();
            activeNormalPanels = new List<PanelBase>();
            activeTopPanels = new List<PanelBase>();
            //Object.DontDestroyOnLoad(canvas);
        }

        public override void Clear()
        {
            panelPool?.Clear();
            panelPool = null;

            activeNormalPanels?.Clear();
            activeNormalPanels = null;

            activeTopPanels?.Clear();
            activeTopPanels = null;

            activeMessageBoxPanels?.Clear();
            activeMessageBoxPanels = null;

            if (canvas != null)
            {
                Object.Destroy(canvas.gameObject);
            }
            canvas = null;
        }

        public override void Restar() { }

        #endregion

        public T Open<T>(PanelContent content) where T : PanelBase
        {
            string path = content.panelPath;
            if(canvas==null)  canvas = Object.FindObjectOfType<Canvas>();
            T panel;
            if (panelPool.ContainsKey(path))
            { 
                panel = panelPool[path] as T;
            }
            else
            {
                GameObject prefab = SingleBehavior<ResManagerByResources>.getInstance().Load<GameObject>(path);
                GameObject panelGo = Object.Instantiate(prefab);
                panel = panelGo.GetOrAddComponent<T>();
                panel.panelType = content.panelType;
                panel.gameObject.transform.SetParent(GetPanelLayer(panel.panelType),false);
                panel.Init();
                panelPool[path] = panel;
            }
            OpenPanelHleper(panel);
            return panel;
        }

        public void Remove(PanelContent content)
        {
            Remove(content.panelPath);
        }

        public void Remove(string panelId)
        {
            if (!panelPool.ContainsKey(panelId))
                return;
            PanelBase panel = panelPool[panelId];
            Close(panel);
            panel.Clear();
            panelPool.Remove(panelId);
            Object.Destroy(panel.gameObject);
        }

        public void RemoveAll()
        {
            RemoveAll(PanelType.top);
            RemoveAll(PanelType.normal);
            RemoveAll(PanelType.messageBox);
        }

        public void RemoveAll(PanelType panelType) {
            List<PanelBase> panels = GetPanels(panelType);
            RemoveAllPanelHelper(panels);
        }

        public void Close(string panel)
        {
            if (!panelPool.ContainsKey(panel))
                return;
            Close(panelPool[panel]);
        }

        public void Close(PanelBase panel)
        {
            if (panel == null) return;
            panel.Close();

            List<PanelBase> panels = GetPanels(panel.panelType);
            if (panels == null) return;
            panels.Remove(panel);
            if (panels.Count > 0) {
                PanelBase curPanel = panels[panels.Count - 1];
                curPanel.transform.SetAsLastSibling();
            }
        }

        public T Get<T>(PanelContent content) where T : PanelBase
        {
            string path = content.panelPath;
            if (panelPool.ContainsKey(path))
                return panelPool[path] as T;
            return null;
        }

        public void CloseAll()
        {
            CloseAll(PanelType.top);
            CloseAll(PanelType.normal);
            CloseAll(PanelType.messageBox);
        }

        public void CloseAll(PanelType panelType)
        {
            List<PanelBase> panels = GetPanels(panelType);
            CloseAllPanelHelper(panels);
        }

        private void CloseAllPanelHelper(List<PanelBase> panels)
        {
            if (panels == null)
                return;
            for (int i = 0; i < panels.Count; i++) {
                panels[i].Close();
                panels.Remove(panels[i]);
                i--;
            }
        }

        private void OpenPanelHleper(PanelBase panel)
        {
            List<PanelBase> panels = GetPanels(panel.panelType);
            if (panels == null) return;
            if (panels.Contains(panel))
                panels.Remove(panel);
            panels.Add(panel);
            panel.Open();
            panel.transform.SetAsLastSibling();
            //canvasLook.SetUIPos();
        }

        private void RemoveAllPanelHelper(List<PanelBase> panels)
        {
            if (panels == null)
                return;
            for (int i = 0; i < panels.Count; i++)
            {
                PanelBase panel = panels[i];
                panel.Close();
                panel.Clear();
                Object.Destroy(panel.gameObject);
                panels.RemoveAt(i);
                i--;
                
            }
        }

        private List<PanelBase> GetPanels(PanelType panelType) {
            switch (panelType) {
                case PanelType.normal:return activeNormalPanels;
                case PanelType.messageBox: return activeMessageBoxPanels;
                case PanelType.top: return activeTopPanels;
                default: return activeNormalPanels;
            }
        }

        private RectTransform GetPanelLayer(PanelType panelType)
        {
            string nodeName = panelType.ToString();
            RectTransform node = canvas.transform.Find(nodeName) as RectTransform;
            if (node == null)
            {
                GameObject GO = new GameObject(nodeName);
                GO.transform.SetParent(canvas.transform, false);
                GO.transform.SetSiblingIndex((int)panelType);
                node = GO.GetOrAddComponent<RectTransform>();
                node.anchorMin = Vector2.zero;
                node.anchorMax = Vector2.one;
                node.offsetMin = Vector2.zero;
                node.offsetMax = Vector2.zero;
            }
            return node;
        }
    }
}